
#ifndef P2P_COMMON_HPP
#define P2p_COMMON_HPP

#include "../PublicKey.hpp"
#include "../muduo/net/InetAddress.h"
#include "../wire/uint256.hpp"
#include "../muduo/base/Timestamp.h"
#include "../wire/serialize.hpp"
#include <atomic>

typedef KeyID NodeID;
typedef std::vector<unsigned char> bytes;

enum PacketType
{
	PingPacket = 0x00,
	PongPacket =0x01,
	MsgPacket =0x02
};

enum DisconnectReason
{
	DisconnectRequested = 0,
	TCPError,
	BadProtocol,
	UselessPeer,
	TooManyPeers,
	DuplicatePeer,
	IncompatibleProtocol,
	NullIdentity,
	ClientQuit,
	UnexpectedIdentity,
	LocalIdentity,
	PingTimeout,
	UserReason = 0x10,
	NoDisconnect = 0xffff
};


inline bool isPermanentProblem(DisconnectReason _r)
{
	switch (_r)
	{
	case DuplicatePeer:
	case IncompatibleProtocol:
	case NullIdentity:
	case UnexpectedIdentity:
	case LocalIdentity:
		return true;
	default:
		return false;
	}
}

/// @returns the string form of the given disconnection reason.
std::string reasonOf(DisconnectReason _r);


class Node
{
protected:
    muduo::net::InetAddress addr_;
	PublicKey publicKey_;
public:
    Node() = default;
    virtual ~Node() = default;
    Node(Node const&);
    Node(const PublicKey publicKey,const muduo::net::InetAddress& addr):
    	addr_(addr), publicKey_(publicKey){}

    virtual muduo::net::InetAddress const& address() const { return addr_;}
	virtual PublicKey const & publicKey() const { return publicKey_; }  
    virtual NodeID id() const { return publicKey_.getId(); }
    virtual operator bool() const { return publicKey_.isValid();}
	
	ADD_SERIALIZE_METHODS;
	template<typename Stream>
    void Serialize(Stream &s) const {
        ::Serialize(s, publicKey_);
        ::Serialize(s, addr_.toIp());
		::Serialize(s, addr_.toPort());
    }

    template<typename Stream>
    void Unserialize(Stream &s) {
        std::string ip;
		uint16_t port;
        ::Unserialize(s, publicKey_);;
        ::Unserialize(s, ip);
		::Unserialize(s, port);
		addr_=muduo::net::InetAddress(ip,port);
    }
};

#endif